﻿//using FFmpeg.AutoGen;
//using FFmpegLib;
//using MediaLib.Interface;
//using OpenTK.Audio.OpenAL;
//using System;
//using System.Buffers;
//using System.IO;
//using System.Threading;
//using System.Threading.Tasks;
//using static MediaLib.OpenALExtension;

//namespace MediaLib.Implement
//{
//    public unsafe class AudioPlayer : IAudioPlayer
//    {
//        private static ArrayPool<byte> _pool = ArrayPool<byte>.Shared;

//        /// <summary>
//        /// 设备
//        /// </summary>
//        private ALDevice _device;
//        /// <summary>
//        /// 上下文
//        /// </summary>
//        private ALContext _alc;
//        /// <summary>
//        /// 当前错误信息
//        /// </summary>
//        private ALError _error;
//        private int _sid;
//        private int _bufferSize;
//        private byte[] _buffer;
//        private FileStream _stream;
//        private int _streamIndex;
//        private ALFormat target_fmt;
//        private CancellationTokenSource _cancelSource;
//        private AVSampleFormat out_sample_fmt = AVSampleFormat.AV_SAMPLE_FMT_NONE;
//        private OpenALUtilities _openAL;

//        public ALSourceState CurCtlStatus { get; set; }
//        public string AudioFile { get; private set; }
//        public int Size { get; private set; }
//        public int SampleRate { get; private set; }
//        public long Bitrate { get; private set; }
//        public int ChannelNum { get; private set; }
//        public int DepthBit { get; private set; }
//        public int PerSampleSize { get; private set; }
//        public FAVStream AudioStreamInfo { get; private set; }

//        private FAudioFifo Fifo;
//        private FSwrContext SwrCtx;
//        public Action<FAVStream> DisplayInfo;

//        public AudioPlayer(string audioFile = null)
//        {
//            AudioFile = audioFile;
//        }


//        #region IAudioPlayer Members
//        public void Play()
//        {
//            InFmtCtx ??= new FAVFormatContext();
//            if (!InFmtCtx.FmtCtxIsOpen)
//                InFmtCtx.OpenFmtCtx(AudioFile);
//            if (!InFmtCtx.FmtCtxIsOpen) { return; }

//            DisplayInfo?.Invoke(InFmtCtx.AudioStream);
//            _openAL = new SilkOpenALUtilities();
//            _openAL.Init();
//            if (!_openAL.Initialization) { return; }

//            PlayByFFmpeg();
//        }

//        public void Pause()
//        {
//            AL.GetSource(_sid, ALGetSourcei.SourceState, out int stat);
//            ALSourceState curStat = (ALSourceState)stat;//AL.GetSourceState(_sid);
//            if (curStat == ALSourceState.Playing)
//                AL.SourcePause(_sid);
//            else if (curStat == ALSourceState.Paused)
//                AL.SourcePlay(_sid);
//        }

//        public void Stop()
//        {
//            AL.SourceStop(_sid);
//            CloseAudioDevice();
//        }

//        public void AdjustVolume(float vol)
//        {
//            AL.Source(_sid, ALSourcef.Gain, vol);
//        }

//        public void AdjustSpeed(float vol)
//        {
//            AL.SpeedOfSound(vol);
//        }

//        /// <summary>
//        /// 获取文件信息
//        /// </summary>
//        /// <param name="audioFile"></param>
//        /// <param name="bitrate">比特率</param>
//        /// <param name="sampleRate">采样率</param>
//        /// <param name="channelNum">通道数</param>
//        /// <param name="depthBit">位深</param>
//        /// <param name="size">文件大小(Byte)</param>
//        public void GetAudioInfo(string audioFile, out long bitrate, out int sampleRate, out int channelNum, out int depthBit, out int size)
//        {
//            bitrate = 0;
//            sampleRate = 0;
//            channelNum = 0;
//            depthBit = 0;
//            size = 0;
//            ////FFmpeg.SetExecutablesPath("");
//            //IMediaInfo media = Xabe.FFmpeg.FFmpeg.GetMediaInfo(audioFile).GetAwaiter().GetResult();
//            //IAudioStream audio = media.AudioStreams.FirstOrDefault();
//            //sampleRate = audio.SampleRate;
//            //channelNum = audio.Channels;
//            //size = (int)media.Size;
//            //bitrate = audio.Bitrate;
//            //depthBit = (int)bitrate / sampleRate / channelNum;
//        }
//        #endregion

//        #region OpenAL处理pcm

//        private void OpenAudioDevice()
//        {
//            _error = OpenDevice(out _device, out ALContext _alc);
//        }

//        private void CloseAudioDevice()
//        {
//            _openAL.CloseDevice();
//        }

//        private void PlayWav()
//        {
//            // 缓存8s的音频数据
//            _bufferSize = SampleRate * ChannelNum * (DepthBit / 8) * 8;
//            target_fmt = GetALFormat(ChannelNum, DepthBit);

//            // 初始化缓冲区
//            _stream = new FileStream(AudioFile, FileMode.Open, FileAccess.Read, FileShare.Read);
//            Size = (int)_stream.Length;
//            _buffer = _pool.Rent(_bufferSize);
//            LoadChunk(); LoadChunk();
//            _cancelSource = new CancellationTokenSource();
//            Task.Factory.StartNew(ListenningBufferQueue, _cancelSource.Token);
//            AL.SourcePlay(_sid);
//        }

//        private void ListenningBufferQueue()
//        {
//            // 读取排队碎片数量
//            AL.GetSource(_sid, ALGetSourcei.BuffersQueued, out int queuedNum);
//            while (queuedNum > 0)
//            {
//                int processdNum; // 已失效数据段数
//                AL.GetSource(_sid, ALGetSourcei.BuffersProcessed, out processdNum);
//                if (processdNum > 0)
//                {
//                    do
//                    {
//                        int bid = 0;
//                        AL.SourceUnqueueBuffers(_sid, 1, ref bid);
//                        AL.DeleteBuffer(bid);
//                        processdNum--;
//                    } while (processdNum > 0);
//                }
//                // 检查排队数量
//                AL.GetSource(_sid, ALGetSourcei.BuffersQueued, out queuedNum);
//                if (queuedNum == 1 && _streamIndex < Size - 1) // 排队数据==1，加一个数据段排队
//                {
//                    LoadChunk();
//                    // 刷新排队数量
//                    AL.GetSource(_sid, ALGetSourcei.BuffersQueued, out queuedNum);
//                }
//                Thread.Sleep(500);
//            }
//        }

//        private void LoadChunk()
//        {
//            int tmp = Size - _streamIndex;
//            if (tmp < _bufferSize) { _bufferSize = tmp; }
//            //if (_buffer == null) { _buffer = _pool.Rent(_bufferSize); }
//            _stream.Read(_buffer, 0, _bufferSize);
//            _streamIndex += _bufferSize;

//            int bid = AL.GenBuffer();
//            AL.BufferData<byte>(bid, target_fmt, _buffer, SampleRate);
//            AL.SourceQueueBuffer(_sid, bid);
//        }

//        #endregion

//        #region FFmpeg.AutoGen
//        private FAVFormatContext InFmtCtx;

//        public void PlayByFFmpeg()
//        {
//            AudioStreamInfo = InFmtCtx.AudioStream;

//            CurCtlStatus = ALSourceState.Playing;
//            _cancelSource = new CancellationTokenSource();
//            Task.Factory.StartNew(LoadAudioWorkThread, _cancelSource.Token);
//            Task.Factory.StartNew(PlayAudioWorkThread, _cancelSource.Token);
//            _openAL.SourcePlay();
//        }

//        /// <summary>
//        /// 判断是否需要继续加载
//        /// </summary>
//        /// <returns></returns>
//        private bool NeedLoad()
//        {
//            if (CurCtlStatus != ALSourceState.Playing)
//                return false;
//            if (Fifo == null)
//                return true;
//            int fifoToRead = Fifo.Size();
//            return fifoToRead < 20000;
//        }

//        public void LoadAudioWorkThread()
//        {
//            using FAVPacket packet = new FAVPacket();
//            using FAVFrame frame = new FAVFrame();
//            while (!disposedValue)
//            {
//                if (NeedLoad())
//                    LoadByFFmpeg(packet, frame);
//                else
//                    ffmpeg.av_usleep(10000u);

//                packet.UnRef();
//                frame.UnRef();
//            }
//            packet.Dispose();
//            frame.Dispose();
//        }


//        /// <summary>
//        /// OpenAL播放状态控制任务
//        /// </summary>
//        public void PlayAudioWorkThread()
//        {
//            while (!disposedValue)
//            {
//                ffmpeg.av_usleep(10000);
//                if (Fifo != null)
//                {
//                    // 读取排队片段数
//                    int queuedNum = _openAL.BuffersQueued();
//                    // 读取当前源播放状态
//                    ALSourceState curStat = _openAL.GetSourceState();

//                    #region 控制播放状态
//                    if (CurCtlStatus == ALSourceState.Playing && queuedNum > 0 && curStat != ALSourceState.Playing)
//                    {
//                        _openAL.SourcePlay();
//                    }
//                    else if (CurCtlStatus == ALSourceState.Paused && curStat == ALSourceState.Playing)
//                    {
//                        _openAL.SourcePause();
//                    }
//                    else if (CurCtlStatus == ALSourceState.Stopped)
//                    {
//                        _openAL.SourceStop();
//                        Dispose();
//                        break;
//                    }
//                    #endregion

//                    #region 检查为播放片段的排队数
//                    if (CurCtlStatus == ALSourceState.Playing && queuedNum < 3)
//                    {
//                        void* pcmData = Fifo.Dequeue(5000, out int dataSize);
//                        if (dataSize > 0)
//                        {
//                            _openAL.QueueBuffer(pcmData, dataSize, target_fmt, SampleRate);
//                            System.Runtime.InteropServices.Marshal.FreeHGlobal(new IntPtr(pcmData));
//                        }
//                    }
//                    #endregion
//                }

//                //检查并清除已播放的缓存
//                _openAL.ClearUnqueueBuffers();
//            }
//        }

//        private void LoadByFFmpeg(FAVPacket packet, FAVFrame frame)
//        {
//            if (InFmtCtx == null || !InFmtCtx.FmtCtxIsOpen)
//                return;

//            try
//            {
//                int ret = InFmtCtx.ReadPacket(packet);
//                if (ret < 0 || packet.StreamIndex != InFmtCtx.AudioIndex)
//                    return;

//                ret = InFmtCtx.Decode(packet, frame);
//                if (ret < 0)
//                    return;
//            }
//            catch (Exception ex) { }

//            frame.TimeBase = InFmtCtx.AudioStream.TimeBase;

//            if (target_fmt == 0)
//            {
//                SampleRate = frame.SampleRate;
//                ChannelNum = frame.Channels;
//                (AVSampleFormat avFmt, ALFormat alFmt) = AVSampleFmtToALFmt(frame.AudioFormat, frame.Channels);
//                target_fmt = alFmt;
//                out_sample_fmt = avFmt;
//                PerSampleSize = ffmpeg.av_get_bytes_per_sample(out_sample_fmt);
//                Fifo ??= new FAudioFifo(out_sample_fmt, ChannelNum);

//                SwrCtx ??= new FSwrContext(frame, out_sample_fmt);
//                if (SwrCtx.Inited == false)
//                    return;
//            }

//            if (Fifo == null)
//                throw new ArgumentException("AudioDecodeUtil->_fifo初始化异常");

//            PcmFrame pcm = null;
//            try
//            {
//                pcm = SwrCtx.ConvertAudioPcmData(frame, out_sample_fmt);
//                if (pcm.NbSamples > 0)
//                    Fifo.Enqueue(pcm.Pcm, pcm.NbSamples);
//            }
//            finally
//            {
//                pcm?.Dispose();
//            }
//            return;
//        }

//        #endregion

//        #region Dispose
//        private bool disposedValue;

//        protected virtual void Dispose(bool disposing)
//        {
//            if (!disposedValue)
//            {
//                if (disposing)
//                {
//                    // TODO: 释放托管状态(托管对象)
//                    CloseAudioDevice();
//                    _stream?.Dispose();
//                }

//                // TODO: 释放未托管的资源(未托管的对象)并重写终结器
//                // TODO: 将大型字段设置为 null
//                disposedValue = true;
//            }
//        }

//        public void Dispose()
//        {
//            // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
//            Dispose(disposing: true);
//            GC.SuppressFinalize(this);
//        }
//        #endregion

//        public static ValueTuple<AVSampleFormat, ALFormat> AVSampleFmtToALFmt(AVSampleFormat in_fmt, int channels)
//        {
//            ALFormat out_ALFmt = 0;
//            AVSampleFormat av_fmt = AVSampleFormat.AV_SAMPLE_FMT_NONE;
//            switch (in_fmt)
//            {
//                case AVSampleFormat.AV_SAMPLE_FMT_U8:
//                case AVSampleFormat.AV_SAMPLE_FMT_U8P:
//                    av_fmt = AVSampleFormat.AV_SAMPLE_FMT_U8;
//                    if (channels == 1)
//                        out_ALFmt = ALFormat.Mono8;
//                    else if (channels == 2)
//                        out_ALFmt = ALFormat.Stereo8;
//                    break;
//                case AVSampleFormat.AV_SAMPLE_FMT_S16:
//                case AVSampleFormat.AV_SAMPLE_FMT_S16P:
//                    av_fmt = AVSampleFormat.AV_SAMPLE_FMT_S16;
//                    if (channels == 1)
//                        out_ALFmt = ALFormat.Mono16;
//                    else if (channels == 2)
//                        out_ALFmt = ALFormat.Stereo16;
//                    break;
//                case AVSampleFormat.AV_SAMPLE_FMT_S32:
//                case AVSampleFormat.AV_SAMPLE_FMT_S32P:
//                case AVSampleFormat.AV_SAMPLE_FMT_FLT:
//                case AVSampleFormat.AV_SAMPLE_FMT_FLTP:
//                    av_fmt = AVSampleFormat.AV_SAMPLE_FMT_S16;
//                    if (channels == 1)
//                        out_ALFmt = ALFormat.Mono16;
//                    else if (channels == 2)
//                        out_ALFmt = ALFormat.Stereo16;
//                    break;
//                case AVSampleFormat.AV_SAMPLE_FMT_S64:
//                case AVSampleFormat.AV_SAMPLE_FMT_S64P:
//                case AVSampleFormat.AV_SAMPLE_FMT_DBL:
//                case AVSampleFormat.AV_SAMPLE_FMT_DBLP:
//                    av_fmt = AVSampleFormat.AV_SAMPLE_FMT_S16;
//                    if (channels == 1)
//                        out_ALFmt = ALFormat.Mono16;
//                    else if (channels == 2)
//                        out_ALFmt = ALFormat.Stereo16;
//                    break;
//                default:
//                    break;
//            }
//            return (av_fmt, out_ALFmt);
//        }
//    }
//}